<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
          "http://www.w3.org/TR/html4/loose.dtd">

<html lang="en">

<head>
  <meta http-equiv="Content-Type"
        content="text/html; charset=utf-8">
  <meta http-equiv="Content-Style-Type"
        content="text/css">
  <meta http-equiv="Content-Script-Type"
        content="text/javascript">
  <meta name="description"
        content="FreeType Documentation">

  <link rel="icon"
        href="image/favicon_-90.ico">
  <link rel="shortcut icon"
        href="image/favicon_-90.ico">
  <link rel="stylesheet"
        type="text/css"
        href="css/freetype2_-90.css">

  <script type="text/javascript"
          src="../../js/jquery-1.11.0.min.js">
  </script>
  <script type="text/javascript"
          src="../../js/jquery.ba-resize.min.js">
  </script>
  <script type="text/javascript"
          src="../../js/freetype2.js">
  </script>

  <title>On slight hinting, proper text rendering, stem darkening and
    LCD filters</title>
</head>


<body>

<div id="top"
     class="bar">
  <h1><a href="http://freetype.org/index.html">FreeType</a> LCD Support</h1>
</div>


<div id="wrapper">

<div class="colmask leftmenu">
  <div class="colright">
    <div class="col1wrap">
      <div class="col1">

        <!-- ************************************************** -->

        <div id="slight-hinting">
          <h2>On Slight Hinting, Proper Text Rendering, Stem Darkening
            and LCD Filters</h2>
          <div class="date">2015-11-30, contributed by Nikolaus
            Waxweiler (with corrections from Graham Asher), updated
            2015-12-08</div>

          <p><em>This article was originally written for the 2.6.2
              release of FreeType and explains the technical
              background of several features.  The information was
              deemed useful enough to be added to the documentation
              and has therefore been retitled.</em></p>

          <p>FreeType 2.6.2 ships with three interesting details for
            users and developers of rendering libraries that deal with
            text.</p>

          <ul>
            <li>
              <a href="#slight-hinting-invokes-the-native-hinter-if-possible">(S)light
                hinting invokes the native hinter if possible</a>
            </li>
            <li>
              <a href="#experimental-stem-darkening-for-the-auto-hinter">Experimental:
                Stem darkening for the auto-hinter</a>
              <ul>
                <li><a href="#background">Background</a></li>
                <li><a href="#back-to-stem-darkening">Back to stem
                    darkening</a></li>
              </ul>
            </li>
            <li>
              <a href="#disabled-stem-darkening-for-the-autohinter-and-adobes-cff-otf-engine">Disabled
                stem darkening for the autohinter and Adobe’s CFF
                (<code>.otf</code>) engine</a>
            </li>
            <li><a href="#the-default-lcd-filter-for-subpixel-rendering-has-been-changed">The
                default LCD filter for subpixel rendering has been
                changed</a>
            </li>
          </ul>

          <h3 id="slight-hinting-invokes-the-native-hinter-if-possible">(S)light
            hinting invokes the native hinter if possible</h3>

          <p>In the past, setting ‘slight’ hinting via FontConfig or
            configuration GUIs meant that native hints within a font
            were ignored; FreeType’s auto-hinter would analyze the
            font on the fly and automatically do what the font
            designer would have to do at least semi-manually.
            Technically, the auto-hinter set to (s)light snaps glyphs
            to the pixel grid only vertically, just like Adobe’s
            proprietary font engine and in a certain way also
            Microsoft’s ClearType/DirectWrite.  The result is a
            compromise between design fidelity and sharpness that
            preserves inter-glyph spacing, something very important
            for horizontal text such as what you are reading right
            now.  The sharpness has usually been enhanced with
            ‘subpixel rendering’ (ClearType on Windows), exploiting
            the physical properties of modern but low-resolution LCD
            panels.</p>

          <p>This worked out well so far, Ubuntu has been using this
            setting for every font for years now.  Werner Lemberg is
            adding support for more and more scripts and has also spun
            off the code
            into <a href="http://www.freetype.org/ttfautohint/">ttfautohint</a>,
            to help font designers ease the pain of manual
            hinting.</p>

          <p>This also meant that the native hinting machinery of the
            font drivers went unused.  Historically, this decision was
            sound because the native hinting mechanics for Postscript
            (<code>.pfa</code>, <code>.pfb</code>), TrueType
            (<code>.ttf</code>) and OpenType/CFF (<code>.otf</code>)
            were subpar for the longest time.  The PostScript hinter
            still is, but with Adobe’s high-quality OpenType/CFF
            engine contributed to FreeType and recent advances of the
            TrueType driver towards full ClearType support, things
            have changed.</p>

          <p>Setting ‘slight’ hinting usually leads
            to <code>FT_LOAD_TARGET_LIGHT</code>.  This mode implied
            the auto-hinter before and has now been changed to mean
            “Use native vertical-grid-only-snapping if driver and font
            supports it and vertical-grid-only auto-hinter otherwise”.
            Right now, only the OpenType/CFF driver is supported.  In
            the future, this will hopefully include the TrueType
            engine once full support for ClearType arrives.
            Technically, ClearType fonts can and will snap to the
            vertical <em>and</em> the horizontal
            grid <a href="http://www.beatstamm.com/typography/RTRCh4.htm#Sec12">depending
            on several details</a>, but the net result is going in the
            direction we want.</p>

          <p>This decision was driven by my personal whim; I wanted
            native vertical grid-fitting if the font driver and font
            supports it, and the auto-hinter otherwise.  I assume that
            native hints are made more carefully and take the
            (auto-hinting) guesswork out of the process.  Instead of
            introducing per-format configuration in FontConfig and
            fighting <a href="http://www.gtk.org/">GTK</a>/<a href="https://www.gnome.org/">GNOME</a>
            that only support a single global hinting setting, it was
            found to make more sense to change the definition of light
            hinting in FreeType.</p>

          <p>I also hope this change will make it easier for the
            non-Windows-and-Apple ecosystem to switch over to slight
            hinting as the default.  Current full/medium native
            hinting, as is the default, tends to bring out the worst
            in many, many fonts that haven’t seen the same insane
            dedication to on-screen display and hinting as many
            popular Microsoft fonts, for example.  And since ClearType
            is still not fully supported, you usually get a very poor
            default experience.  Slight hinting gives a much better
            one, as Ubuntu has proven over the years.</p>


          <h3 id="experimental-stem-darkening-for-the-auto-hinter">Experimental:
            Stem darkening for the auto-hinter</h3>

          <p><a href="image/freetype-262-autohinter-stem-darkening-demo1.png">
              <img src="image/freetype-262-autohinter-stem-darkening-demo1-thumbnail.png"
                   alt="Demonstration and comparison of the
                        emboldening autohinter."></a></p>

          <p>Stem darkening emboldens glyphs at smaller sizes to make
            them more readable on common low-DPI screens.  If this
            sounds familiar to you, that’s because Adobe’s CFF engine
            has been doing it since it was contributed in 2013.  You
            might have noticed that OpenType/CFF fonts (commonly
            suffixed <code>.otf</code>) like GNOME&nbsp;3’s default UI
            font <a href="https://en.wikipedia.org/wiki/Cantarell_%28typeface%29">Cantarell</a>
            appear bolder and fuzzier than other fonts, at least until
            this release.  The auto-hinter can do the exact same thing
            now, it is just disabled by default.</p>

          <p>But why would you do this if small glyphs are already
            fairly readable?  It turns out that font rendering in the
            Linux ecosystem has been wrong since scalable fonts were
            introduced to it.  Text must be rendered with linear alpha
            blending and gamma correction, which no toolkit or
            rendering library does by default on
            <a href="http://www.x.org/">X11</a>, even
            though <a href="http://www.qt.io/">Qt5</a>
            and <a href="https://skia.org/">Skia</a> (as used by
            Google Chrome and other browsers) can do it.</p>


          <h4 id="background">Background</h4>

          <p>First, to understand why they are required, you must know
            that when FreeType outputs a grayscale glyph image, it
            really outputs a coverage bitmap.  If a pixel is
            completely covered by a filled-in outline, the pixel is
            made 100% black (0% brightness, which is simply black).
            If a pixel is only 50% covered, the pixel is made 50%
            black (50% brightness or a middle shade of gray) and 0%
            covered means 0% black (100% brightness or white).  On
            high-DPI screens like on smartphones and tablets, the
            pixels are so small that the chance of being completely
            covered and therefore completely black is fairly good.  On
            low-DPI screens most of us are sadly stuck with, the
            situation is different.  The pixels are too large for most
            of the details of a glyph and shades of gray are the norm
            rather than the exception.</p>

          <p>This is relevant because all our screens have a second
            problem: they are not linear. 1&nbsp;+&nbsp;1 is
            not&nbsp;2.  Twice the value does not result in twice the
            brightness.  When a pixel is only 50% covered, the
            coverage map says 50% black, and this translates to a
            pixel value of&nbsp;128 when you use 8&nbsp;bits per
            channel (0-255).  However, this does not translate to 50%
            brightness for that pixel on our sRGB and gamma&nbsp;2.2
            screens.  Due to their non-linearity, they dwell longer in
            the darks and only a pixel value of about&nbsp;186 results
            in 50% brightness – 128&nbsp;ends up too dark on both
            bright and dark backgrounds.  The net result is that dark
            text looks burnt-out, pixely and blotchy on bright
            background, bright text too frail on dark backgrounds, and
            colored text on colored background (for example, red on
            green) seems to have dark halos or ‘dirt’ around it.  The
            situation is especially ugly for diagonal stems like in
            glyph ‘w’, where the quality of FreeType’s anti-aliasing
            depends on the correct display of grays.  On high-DPI
            screens where smaller, fully black pixels reign supreme,
            this doesn’t matter, but on our low-DPI screens with all
            the gray shades, it does.  0% and 100% brightness are the
            same things in linear and non-linear space, just all the
            shades in-between are not.</p>

          <p>The correct way of rendering a glyph image on a surface
            is
            to <a href="https://en.wikipedia.org/wiki/Alpha_compositing">alpha
            blend</a> it onto the surface in linear space and then
            apply <a href="https://en.wikipedia.org/wiki/Gamma_correction">gamma
            correction</a> to translate the linear coverage map to
            something that is correct for our screens.<sup>1</sup> No
            toolkit in the Linux ecosystem does it by default, even
            though Qt5 and Skia can and will do it on other platforms.
            Windows and Mac OS&nbsp;X do it natively.  This procedure
            is especially important if glyphs should be
            subpixel-rendered (ClearType and Mac
            OS&nbsp;X) <a href="http://lists.nongnu.org/archive/html/freetype-devel/2015-11/msg00020.html">with
            as few color fringes as possible</a>.</p>

          <p><sup>1</sup> This process can cost performance.  There is
            an approximation that does not need to know about the
            background color.
            See <a href="https://bel.fi/alankila/lcd/">https://bel.fi/alankila/lcd/</a>
            and <a href="https://bel.fi/alankila/lcd/alpcor.html">https://bel.fi/alankila/lcd/alpcor.html</a>
            for details.  There is a proof-of-concept pixman hack for
            cairo.</p>


          <h4 id="back-to-stem-darkening">Back to stem darkening</h4>

          <p>Assume we render fonts correctly.  Gamma correction
            essentially lightens fonts since shades of gray are
            shifted to higher pixel values (corresponding to higher
            brightness) to match the original intention to the reality
            of our screens.  The side-effect is that glyphs that were
            rendered incorrectly but fairly readable suddenly thin
            out.  Correctly rendered but hard-to-read text doesn’t do
            anyone a favor.  So Mac OS&nbsp;X and Adobe’s proprietary
            font engine implement a counter-measure: stem darkening at
            smaller sizes where shades of gray dominate.  By
            emboldening a glyph slightly in relation to its pixel
            size, individual pixels get higher coverage of filled-in
            outlines and are therefore blacker.  This increases
            contrast and prevents thinning out of glyphs.  Text
            remains readable at smaller sizes.</p>

          <p><a href="image/BlendingExamples.png">
              <img src="image/BlendingExamples-thumbnail.png"
                   alt="Comparison of different ways of
                        blending."></a></p>

          <p>“Gamma 1.0” shows what happens when you take a grayscale
            coverage bitmap from FreeType and blend it onto a surface
            in linear space.  Black-on-white is heavier than
            white-on-black and red-on-green has dark halos or dirt
            around it.  Note that this picture is unrealistic in the
            sense that no rendering system on X11 does linear alpha
            blending, so imagine something worse.  “Gamma 1.8” is the
            result of linear alpha blending and gamma correction.  It
            is much better, but text thins out, making it harder to
            read.  Adding stem darkening gets us to “Gamma 1.8,
            darkened”.  Note how it is the cleanest rendering of all.
            “Gamma 1.0, darkened”, meaning linear alpha blending
            without gamma correction but with stem darkening,
            exaggerates the effects of “Gamma 1.0”.  Stem darkening
            should only be enabled when doing gamma correction, so
            ideally it should always be done.</p>

          <p><a href="image/freetype-262-autohinter-stem-darkening-demo2.png">
              <img src="image/freetype-262-autohinter-stem-darkening-demo2-thumbnail.png"
                   alt="Waterfall comparison of non-emboldening and
                        emboldening autohinter."></a></p>

          <p>The autohinter has a new toggleable stem darkening
            property that works like the stem darkener in Adobe’s CFF
            engine.  Note how it makes text slightly bolder with the
            default parameters, down to small pixel sizes.  Gamma
            correction is active to demonstrate the thinning out of
            text especially at smaller pixel sizes with lots of gray
            pixels.</p>

          <p>And that is the story behind this feature.</p>


          <h3 id="disabled-stem-darkening-for-the-autohinter-and-adobes-cff-otf-engine">Disabled
            stem darkening for the autohinter and Adobe’s CFF
            (<code>.otf</code>) engine</h3>

          <p>No library supports linear alpha blending and gamma
            correction out of the box on X11.  Turning on stem
            darkening leads to heavy and fuzzy looking glyphs as in
            “Gamma 1.0, darkened” above, so it’s better to disable
            it.</p>

          <p>Qt5 actually had gamma correction enabled for a short
            time while until someone complained that text was too
            light and unlike rendering in other toolkits, so the
            maintainers disabled it for
            the <a href="https://bugreports.qt.io/browse/QTBUG-41590">XCB-backend</a>.
            Skia (Chrome) can do gamma-correction, but turns it off
            for X11.</p>

          <p>I see autohinter stem darkening as a technology preview
            for playing around with until we get stem darkening
            generic within FreeType.  The plan is to provide it for
            all font drivers and make it toggleable
            per <code>FT_Library</code> just like
            <code>FT_Library_SetLcdFilter</code>.  Libraries that
            support linear alpha blending and gamma correction can
            then just flip the switch and get appropriate glyphs no
            matter the font.</p>

          <p>A notable side-effect of disabling all stem darkening by
            default is that natively hinted <code>.otf</code> fonts
            will render remarkably similar to the auto-hinter and are
            no longer heavy and fuzzy.  Slight hinting will result in
            consistent font rendering.</p>


          <h3 id="the-default-lcd-filter-for-subpixel-rendering-has-been-changed">The
            default LCD filter for subpixel rendering has been
            changed</h3>

          <p><a href="image/freetype-262-new-old-filter.png">
              <img src="image/freetype-262-new-old-filter-thumbnail.png"
                   alt="Comparison of the old and new
                        filter."></a></p>

          <p>When you look at subpixel-rendered text, no matter
            whether it is on some kind of Unix, Windows, or Mac
            OS&nbsp;X, you might notice that it is slightly colored.
            Using subpixel rendering on LCD panels is a trade-off; you
            get three times higher resolution in the direction of the
            pixel-substripe (usually horizontal RGB) in exchange for
            color artifacts, also called color fringes.  For this
            reason it is necessary to filter a subpixel-rendered glyph
            to reduce those color fringes before putting it somewhere
            on the screen.  The filter distributes the values of a
            subpixel to its neighbors, sacrificing some of the higher
            resolution and making the resulting glyph image blurrier,
            but the positioning improvement remains!  The ideal filter
            for you depends on your screen (gamma curves), the
            capabilities of the rendering system (linear alpha
            blending and gamma correction), your vision and your
            taste, probably in that order.</p>

          <p>A filter should have two properties: it should be
            normalized, meaning the values used in the filter should
            sum up to a figurative&nbsp;1 (here: 0x100 or 256) and it
            should be color-balanced, meaning that values for one
            subpixel are equally distributed to all other subpixels of
            a pixel to sacrifice some of the higher resolution to
            drastically reduce color fringes.</p>

          <p>Previously, FreeType’s default LCD filter was neither
            normalized nor color-balanced.  That was a deliberate
            choice because there is still no rendering system on
            Unix-like operating systems that does linear alpha
            blending and gamma correction by default to render glyphs
            correctly.  Going above a filter sum of&nbsp;1 increased
            contrast somewhat at the expense of slight distortions and
            increased color-fringing, so this can be seen as a hack.
            You might have noticed that thumbnails in various places
            on your computer that show text could be quite colorful.
            Now you know why.</p>

          <p>The new default filter is both normalized and
            color-balanced.  It is indeed ever so slightly blurrier
            than the previous default one, but also lacks its
            harshness and is less color-happy.  The blurriness also
            means higher tolerance for non-ideal screen gamma (viewing
            angles) and rendering systems without linear alpha
            blending.  Note that color fringes can only be really
            minimized when the rendering system will do linear alpha
            blending of text.</p>

          <p>The ‘light’ filter that has accompanied the default one
            for so long stays unchanged: it already is normalized and
            color-balanced.  It is sharper than the default one but
            less tolerant of uncalibrated screens and rendering
            systems without linear alpha blending, producing more
            color fringes.</p>
        </div>

        <!-- ************************************************** -->

        <div class="updated">
          <p>Last update: 13-Feb-2018</p>
        </div>
      </div>
    </div>


    <!-- ************************************************** -->

    <div class="col2">
    </div>
  </div>
</div>


<!-- ************************************************** -->

<div id="TOC">
  <ul>
    <li class="funding">
      <form action="https://www.paypal.com/cgi-bin/webscr"
            method="post"
            target="_top">
        <input type="hidden"
               name="cmd"
               value="_s-xclick">
        <input type="hidden"
               name="hosted_button_id"
               value="SK827YKEALMT4">
        <input type="image"
               src="https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif"
               name="submit"
               alt="PayPal - The safer, easier way to pay online!">
        <img alt=""
             border="0"
             src="https://www.paypalobjects.com/de_DE/i/scr/pixel.gif"
             width="1"
             height="1">
      </form>
    </li>
    <li class="primary">
      <a href="http://freetype.org/index.html">Home</a>
    </li>
    <li class="primary">
      <a href="http://freetype.org/index.html#news">News</a>
    </li>
    <li class="primary">
      <a href="index.html">Overview</a>
    </li>
    <li class="primary">
      <a href="documentation.html">Documentation</a>
    </li>
    <li class="primary">
      <a href="http://freetype.org/developer.html">Development</a>
    </li>
    <li class="primary">
      <a href="http://freetype.org/contact.html"
         class="emphasis">Contact</a>
    </li>

    <li>
      &nbsp; <!-- separate primary from secondary entries -->
    </li>

    <li class="secondary">
      <a href="#slight-hinting" class="current">On Slight
        Hinting,&nbsp;&hellip;</a>
    </li>
  </ul>
</div>

</div> <!-- id="wrapper" -->

<div id="TOC-bottom">
</div>

</body>
</html>
